package fileby.model.impl.sources.impl;

import fileby.model.impl.sources.FileItem;
import fileby.core.IDisplayableFile;
import fileby.core.SourceType;
import fileby.core.IDisplayableFileSource;
import fileby.model.impl.sources.IFileSource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.Icon;

/**
 *
 * @author Jacob
 */
public abstract class AbstractFileSource implements IFileSource {

    ArrayList<FileItem> files = new ArrayList();
    SourceType sourceType;
    String name;
    Icon icon;
    boolean writePermission;
    boolean changePermission;

    public abstract String getAbsolutePath();

    public abstract IDisplayableFileSource getParent();

    public abstract boolean addFiles(List<File> fileList, int action) throws IOException;

    public abstract void updateContent();

    public ArrayList<FileItem> getFileItems() {
        return files;
    }

    public ArrayList<IDisplayableFile> getFiles() {
        return new ArrayList(files);
    }

    public void setSingleSelected(String path) {
        setAllSelected(false);
        setSelected(path, true);
    }

    public void setSelected(String path, boolean b) {
        for (FileItem f : files) {
            if (f.getFile().getAbsolutePath().equals(path)) {
                f.setSelected(b);
                break;
            }
        }
    }

    public void setAllSelected(boolean b) {
        for (FileItem f : files) {
            f.setSelected(b);
        }
    }

    public boolean canAdd() {
        return writePermission;
    }

    public boolean canEdit() {
        return changePermission;
    }

    public SourceType getSourceType() {
        return sourceType;
    }

    public String getName() {
        return name;
    }

    public Icon getIcon() {
        return icon;
    }

    @Override
    public String toString() {
        return sourceType.toString() + ";" + name;
    }

    public boolean syncList(List<File> updatedFiles) {
        boolean filesChanged = false;
        // Find and add any new files found in the original source
        for (File file : updatedFiles) {
            boolean newFile = true;
            for (FileItem fileItem : files) {
                if (fileItem.getFile().equals(file)) {
                    newFile = false;
                    break;
                }
            }
            if (newFile) {
                filesChanged = true;
                files.add(new FileItem(file));
            }
        }

        // Remove any files which have been removed from original source
        ArrayList<FileItem> fileItemsScheduledForDeletion = new ArrayList();
        for (FileItem fileItem : files) {
            boolean fileItemRemains = false;
            for (File f : updatedFiles) {
                if (fileItem.getAbsolutePath().equals(f.getAbsolutePath())) {
                    fileItemRemains = true;
                    break;
                }
            }
            if (!fileItemRemains) {
                filesChanged = true;
                fileItemsScheduledForDeletion.add(fileItem);
            }
        }
        files.removeAll(fileItemsScheduledForDeletion);
        return filesChanged;
    }

    public void sortList() {
        Collections.sort(files, getFileItemComparator());
    }

    private Comparator<FileItem> getFileItemComparator() {
        return new Comparator<FileItem>() {

            public int compare(FileItem o1, FileItem o2) {
                if (o1.isDirectory()) {
                    if (o2.isDirectory()) {
                        return o1.getAbsolutePath().compareToIgnoreCase(o2.getAbsolutePath());
                    }
                    return -1;
                } else if (o2.isDirectory()) {
                    return 1;
                }
                return o1.getAbsolutePath().compareToIgnoreCase(o2.getAbsolutePath());
            }
        };
    }

}
